#ifndef TIMEREVENTQUEUE_H
#define TIMEREVENTQUEUE_H
#include "InterruptHandler.h"

class TimerEventListener
{
public:
    virtual long unsigned onTime()=0;

};
struct EventElement
{
    EventElement(TimerEventListener* obj, unsigned long ptime)
    {
        callback=obj;
        time = ptime;
    }
    EventElement()
    :callback(0),time(0)
    {}
    TimerEventListener* callback;
    unsigned long time;
};

#define LISTMAXLEN 20
class List
{
public:
    void insert(const EventElement& elemToInsert)
    {
        unsigned short count(0);
        if(eventCount +1 < LISTMAXLEN)
		{
			eventList[eventCount] = elemToInsert;
            eventCount++;
		}
        else
		{
			Serial.println("queue overflow");
            return;
		}
    }

    void popFront(long unsigned ptime)
    {
        int count(0);
        //while(eventCount > 0 && eventList[currentHead].time <  ptime && count++<LISTMAXLEN)
		for(int i = 0; i < eventCount; ++i)
        {
            unsigned int adjustment(0);
            if(eventList[i].callback != 0 )
            {
				if(eventList[i].time <  ptime)
				{
					adjustment = eventList[i].callback->onTime();
					eventList[i].time = ptime + adjustment;
					if(adjustment == 0)
					{
						swap(i,eventCount-1);
						eventCount--;
					}
				}
            }
            else{
                Serial.println("GAAAAAAAAAAAAAAA nullptr");
                break;
            }
        }
    }
    ~List(){}
    List()
    : eventCount(0)
    {}
private:
    void swap(unsigned short first, unsigned short second)
    {
        EventElement tmp = eventList[second];
        eventList[second] = eventList[first];
        eventList[first] = tmp;
    }
    unsigned short eventCount;
    EventElement eventList[LISTMAXLEN];
};
class TimerQueue
{
public:
    void registerTimerEvent(TimerEventListener* obj, unsigned long time)
    {
        _eventList.insert(EventElement(obj, micros()+time));
    }
    void periodicTimerTick(unsigned long time = 0)
    {
        _eventList.popFront(time==0?micros():time);
    }
private:
    List _eventList;
};

#endif // TIMEREVENTQUEUE_H
